﻿#region licence
//  Copyright 2008 Michael Cromwell

//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at

//       http://www.apache.org/licenses/LICENSE-2.0

//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net.Appender;
using log4net.Core;
using Boo.Lang;
using log4net.altconf.Macros;
using Boo.Lang.Compiler.Ast;

namespace log4net.altconf
{
    /// <summary>
    /// DSL base class, implemented by Rhino DSL
    /// </summary>
    public abstract class Log4NetDslConfiguration
    {
        protected IDictionary<string, IAppender> appenders = new Dictionary<string, IAppender>();
        protected IList<LogDetails> logs = new System.Collections.Generic.List<LogDetails>();
        protected IQuackFu currentAppender;
        protected LogDetails currentLog;
        private Level internalThreshold = Level.All;
        
        /// <summary>
        /// Hook method for Rhino DSL
        /// </summary>
        public abstract void Process();
        
        #region levels

        protected Level FATAL = Level.Fatal;
        protected Level DEBUG = Level.Debug;
        protected Level ERROR = Level.Error;
        protected Level INFO = Level.Info;
        protected Level VERBOSE = Level.Verbose;
        protected Level WARNING = Level.Warn;

        #endregion
        
        public virtual bool debug {get;set;}
        public virtual Level threshold
        {
            get { return internalThreshold; }
            set { internalThreshold = value; }
        }
                
        public virtual void LogFor(string name, Action action)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentException("name cannot be null or empty.", "name");

            currentLog = new LogDetails();
            currentLog.Name = name;
            logs.Add(currentLog);

            action();
        }

        public virtual IList<LogDetails> Logs
        {
            get { return logs; }
        }

        public virtual void UseAppenders(params string[] appenders)
        {
            if (currentLog == null)
                throw new NoCurrentLogException();

            foreach (var appender in appenders)
                if (!this.appenders.ContainsKey(appender))
                    throw new AppenderNotFoundException(appender);
                else
                    currentLog.Appenders.Add(this.appenders[appender]);
        }

        public virtual void AtLevel(Level level)
        {
            if (currentLog == null)
                throw new NoCurrentLogException();

            currentLog.Level = level;
        }

        public virtual void AddAppender(string name, Type type)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentException("name cannot be null or empty.", "name");

            if (!typeof(IAppender).IsAssignableFrom(type))
                throw new ArgumentException(string.Format("type supplied must be assignable to {0}",typeof(IAppender).FullName) , "type");

            var instance = Activator.CreateInstance(type) as IAppender;
            instance.Name = name;
            currentAppender = new AppenderQuackFuAdapter(instance);
            appenders.Add(name, (IAppender)instance);
        }

        public virtual void IgnoreInheritedAppenders()
        {
            if (currentLog == null)
                throw new NoCurrentLogException();

            currentLog.Additivity = true;
        }

        public virtual string EnvironmentVariable(string name)
        {
            return Environment.GetEnvironmentVariable(name);
        }
    }

  
}
